package org.jeecg.modules.cascv.image.service.video;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.HexUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.lineparser.Line;
import org.jeecg.common.lineparser.LineParser;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.javacpp.Pointer;
import org.bytedeco.javacpp.avformat;
import org.jeecg.modules.cascv.image.util.LaptopConstant;
import org.jeecg.modules.cascv.image.util.LaptopUtil;
import org.jeecg.modules.cascv.image.util.MergeUtil;

import java.io.File;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

@Slf4j
public class ReadCallback extends avformat.Read_packet_Pointer_BytePointer_int  {
//建立连接 从这边拉流   //读文件
    @SneakyThrows
    @Override
    public int call(Pointer opaque, BytePointer buf, int buf_size) {

        try {
            String keyAndVersion = LaptopConstant.pointerAndConVer.get(opaque); //opaque ==ifmt_ctx  ifmt_ctx.pb(avio);
            System.out.println("call=" + keyAndVersion);
            String[] arr = keyAndVersion.split("#");
            String key = arr[0];
            String version = arr[1];
            String isReal = arr[2];
            String userId = arr[3];

            Integer currVersion = 0;
            AtomicInteger atomicInteger = LaptopConstant.clientVersionMap.get(userId);
            if(atomicInteger == null){
                currVersion = -1;
            }else{
                currVersion = atomicInteger.get();
            }

            if(Integer.parseInt(version) - currVersion != 0){
                return 0;
            }

            //文件的偏移量：上次读到100行了 这次就从101开始
            Long oldOffset = LaptopConstant.offsetMap.get(key + "#" + userId + "#" + version);
            if(oldOffset == null){
                oldOffset = 0L;
            }
            System.out.println("oldOffset=" + oldOffset);

//            Path path = Paths.get("D:\\pc_workspace\\2.h264str");
//            Path path = Paths.get("D:\\pc_workspace\\t1.h264");
            //根据key 知道文件存放的位置
            String filePath = LaptopConstant.filePathMap.getOrDefault(key,"");
            System.out.println("filePath=" + filePath);
//            Path path = Paths.get("//files//t1.h264");
            //根据路径声Path对象
            Path path = Paths.get(filePath);
//            path = Paths.get("d:\\files\\t1.h264");
//          获取文件 获取文件大小
            long length = path.toFile().length();

            if(oldOffset >= length){ //判断索引有没有超过文件大小，就是异常数据
                System.out.println("read end=" + oldOffset  + ">=" + length);
                return 0;
            }

            Charset cs = StandardCharsets.UTF_8;
            //按行读，传入上次的oldOffset 如果第一次就是0从头开始
            LineParser parser = new LineParser(Integer.MAX_VALUE, oldOffset);

            ByteBuf appendbuf = Unpooled.buffer(10);

            AtomicInteger maxPushNum = new AtomicInteger(0);
            final Long[] offset = {0L};
            int pushNum = 10; //一次性读10行

            final JSONObject[] lastDataItem = {null};

            try {
                parser.forEach(path, cs, new Consumer<Line>() {
                    @Override
                    public void accept(Line line) {
                        if(line.getLength() <= 100){ //异常帧
                           return;
                        }
                        if (maxPushNum.get() < pushNum) {
                            log.info(maxPushNum.get() + "," + pushNum + ",offset=" + line.getOffset() + ",len=" + line.getLength());
                            JSONObject dataItem = JSON.parseObject(line.getContent().toString());
                            String secondStr = dataItem.getString("second");
                            String subsecondStr = dataItem.getString("subsecond");
                            String tableName = dataItem.getString("tableName");
                            LaptopConstant.tableNameMap.put(key + "#" + userId + "#" + version,tableName);
                            lastDataItem[0] = dataItem;
                            dataItem = dataItem.getJSONObject("Content");
                            System.out.println("---readcallback :=====: " + secondStr+"---");
//                            dataItem.put("second",secondStr);
//                            dataItem.put("subsecond",subsecondStr);
                            //读取数据区 表格里显示
                            String videoStr = dataItem.getString(LaptopConstant.FRAME_FIELD_MAP.get(tableName));//todo
                            dataItem.remove(LaptopConstant.FRAME_FIELD_MAP.get(tableName));

                            //截取0x ;之类的东西
                            videoStr = (videoStr.split(";")[1]).substring(2).trim();
                         //  videoStr = StringUtils.substring(videoStr, 7, videoStr.length() - 10);
                             //videoStr = StringUtils.substring(videoStr, 7, videoStr.length() - 16);

//                            System.out.println("videoStr=" + videoStr.substring(0, 10));
                            //转二进制流
                            byte[] bytes = HexUtil.decodeHex(videoStr);
//
//                            FileUtil.appendUtf8Lines(Arrays.asList(line.getContent()), "D:\\files\\str-"+keyAndVersion+".h264");
                            FileUtil.writeBytes(bytes, new File("D:\\files\\byte-"+keyAndVersion+".h264"), 0, bytes.length, true);
                            //写成ByteBuf
                            appendbuf.writeBytes(bytes);
                            maxPushNum.incrementAndGet(); //++1
                            offset[0] = line.getOffset() + line.getLength();
//
                        } else {
                            throw new RuntimeException("enough"); //无法终止 然后就抛异常进行终止
                        }
                    }
                });
            } catch (Exception e) {
//                e.printStackTrace();
            }

            if(appendbuf.writerIndex() > 0){
                //偏移量
                LaptopConstant.offsetMap.put(key + "#" + userId + "#" + version, offset[0]);

                JSONObject jsonObject = lastDataItem[0];
                if(jsonObject != null){ //设置播放表格的区域
                    LaptopConstant.dataTableCache.put(key + "#" + userId + "#" + version, jsonObject);
                }
            }

//            System.out.println("put_len=" + appendbuf.writerIndex());

            buf.put(appendbuf.array(), 0, appendbuf.writerIndex());
            return appendbuf.writerIndex();
        } catch (Exception e) {
            log.error("readCallBack error", e);
        }
        return 0;
    }
}